package cc.aiee.bambora.northamerica.api;

import com.beanstream.Gateway;
import com.beanstream.exceptions.BeanstreamApiException;
import com.beanstream.requests.CardPaymentRequest;
import com.beanstream.requests.TokenPaymentRequest;
import com.beanstream.responses.PaymentResponse;

import cc.aiee.bambora.northamerica.config.BamboraPayConfig;
import cc.aiee.bambora.northamerica.config.BamboraPayConfigKit;
import cc.aiee.bambora.northamerica.model.BamboraCardPurchaseModel;
import cc.aiee.bambora.northamerica.model.BamboraRefundModel;
import cc.aiee.bambora.northamerica.model.BamboraTokenPurchaseModel;
import cc.aiee.core.bean.R;
import cc.aiee.core.enums.ErrCodeEnum;
import cc.aiee.core.kit.KitMoney;
import lombok.extern.slf4j.Slf4j;

/**
 * North America(北美地区) API
 * 
 * @author YangLong<br>
 *         2020-11-03 17:03:31
 */
@Slf4j
public class BamboraPayApi {

	public boolean purchase(BamboraTokenPurchaseModel bamboraPurchaseModel) {

		if (log.isDebugEnabled()) {
			log.debug("Bambora Pay purchase,入参信息:\n{}", bamboraPurchaseModel.toJson(true, false));
		}

		Gateway beanstream = new Gateway("v1", 300208941, "E49FCfAD6994481Ca3f8BE56CDa0ee13");
		TokenPaymentRequest tokenReq = new TokenPaymentRequest();

		double amount = KitMoney.toYUAN(bamboraPurchaseModel.getAmount()).doubleValue();
		tokenReq.setAmount(amount);

		tokenReq.setOrderNumber(bamboraPurchaseModel.getOrderNo());
		tokenReq.getToken().setName(bamboraPurchaseModel.getName()).setCode(bamboraPurchaseModel.getLegatoToken());

		try {
			PaymentResponse response = beanstream.payments().makePayment(tokenReq);

			log.debug("Token Payment Approved? {}", response.isApproved());

			return response.isApproved();
		} catch (BeanstreamApiException ex) {
			ex.printStackTrace();
			// TODO handle exception
		}
		return false;
	}

	public R<PaymentResponse> cardPayment(BamboraCardPurchaseModel bamboraCardPurchaseModel) {

		if (log.isDebugEnabled()) {
			log.debug("Bambora Pay Card 入参:\n{}", bamboraCardPurchaseModel.toJson());
		}

		Gateway beanstream = BamboraPayConfigKit.defaultGateway;
		BamboraPayConfig defaultConfig = BamboraPayConfigKit.defaultConfig;

		CardPaymentRequest req = new CardPaymentRequest();

		double amount = KitMoney.toYUAN(bamboraCardPurchaseModel.getAmount()).doubleValue();

		req.setAmount(amount).setMerchantId(defaultConfig.getMerchantId().toString())
				.setOrderNumber(bamboraCardPurchaseModel.getOrderNo());
		req.getCard().setName(bamboraCardPurchaseModel.getCardOwnerName())
				.setNumber(bamboraCardPurchaseModel.getCardNo())
				.setExpiryMonth(bamboraCardPurchaseModel.getCardExpiryMonth())
				.setExpiryYear(bamboraCardPurchaseModel.getCardExpiryYear())
				.setCvd(bamboraCardPurchaseModel.getCardCvd());

		try {
			PaymentResponse response = beanstream.payments().makePayment(req);
			return result(response);
		} catch (BeanstreamApiException ex) {
			ex.printStackTrace();
		}
		return result(null);
	}

	/**
	 * 无效将取消交易，然后再将其注册到客户的信用卡帐户中。持卡人永远不会在其信用卡对帐单上看到无效交易。结果，只能在原始交易的同一天尝试作废。一天结束后（美国东部标准时间/
	 * EDT大约晚上11:59），如果尝试，无效请求将被API拒绝。从那时起，对于该交易，您将需要执行退货。
	 * 
	 * 您可以无效购买和退货，并且必须提供无效的金额。此金额必须等于或等于该交易金额。
	 * 
	 * @param model
	 * @return
	 * @author YangLong <br>
	 *         2020-11-04 15:06:08
	 */
	public R<PaymentResponse> voidPayment(BamboraRefundModel model) {
		Gateway beanstream = BamboraPayConfigKit.defaultGateway;
		try {
			double amount = KitMoney.toYUAN(model.getAmount()).doubleValue();
			PaymentResponse response = beanstream.payments().voidPayment(model.getTransactionId(), amount);
			return result(response);
		} catch (BeanstreamApiException e) {
			e.printStackTrace();
		}
		return result(null);
	}

	public R<PaymentResponse> refund(BamboraRefundModel model) {
		Gateway beanstream = BamboraPayConfigKit.defaultGateway;
		try {
			double amount = KitMoney.toYUAN(model.getAmount()).doubleValue();
			PaymentResponse response = beanstream.payments().returnPayment(model.getTransactionId(), amount);
			return result(response);
		} catch (BeanstreamApiException e) {
			e.printStackTrace();
		}
		return result(null);
	}

	public R<PaymentResponse> result(PaymentResponse response) {
		if (response == null) {
			return new R<>(ErrCodeEnum.e_fail_1);
		}
		if (response.isApproved()) {
			return new R<>(ErrCodeEnum.s_success_0, response);
		}
		return new R<>(response.messageId, response.message, false, response);
	}
}
